﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ashlen.Portal.Core.DataInterfaces;
using Ashlen.Portal.Core;

namespace Ashlen.Portal.Data.SqlServer
{
    public class AdministrationDao : BaseDao, IAdministrativeDao
    {
        public AdministrationDao() : base()
        {}

        public AdministrationDao(string connectionString) : base(connectionString)
        {}

        #region Roles
        public object GetRoles()
        {
            RenewContext();
            var query = from r in Context.aspnet_Roles
                        orderby r.RoleName
                        select new { r.RoleId, r.RoleName, r.Description };
            var ret = query.ToList();
            return ret;
        }

        public void SaveRole(string applicationId, Guid? roleId, string roleName, string description)
        {
            //validations
            if (roleName == null || roleName.Trim().Equals(string.Empty))
            {
                throw new ArgumentException("Role name cannot be null or empty.");
            }
            RenewContext();
            aspnet_Roles role = null;
            if (roleId.HasValue)
            {
                role = Context.aspnet_Roles.FirstOrDefault(r => r.RoleId == roleId.Value && r.aspnet_Applications.ApplicationId == new Guid(applicationId) );
            }
            if (role == null || roleId.Equals(Guid.Empty) || !roleId.HasValue )
            {
                //Insert
                role = new aspnet_Roles();
                role.aspnet_Applications = Context.aspnet_Applications.FirstOrDefault(a => a.ApplicationId == new Guid(applicationId));
                role.RoleId = (roleId.HasValue ? roleId.Value : Guid.NewGuid());
                role.RoleName = roleName;
                role.LoweredRoleName = roleName.ToLower();
                role.Description = description;
                Context.AddToaspnet_Roles(role);
            }
            else
            {
                //Update
                role.RoleName = roleName;
                role.LoweredRoleName = roleName.ToLower();
                role.Description = description;
            }
            Context.SaveChanges();
        }

        public void DeleteRole(Guid roleId)
        {
            RenewContext();
            var role = Context.aspnet_Roles.FirstOrDefault(r => r.RoleId == roleId);
            if (role != null)
            {
                Context.DeleteObject(role);
                Context.SaveChanges();
            }
        }
        #endregion

        #region Users
        public object GetUsers(string partialUsername)
        {
            RenewContext();
            var users = from u in Context.aspnet_Users
                        where ( (partialUsername == null || partialUsername == string.Empty) ||
                        (u.aspnet_UserPersonalInfo.Firstname.Contains(partialUsername) || u.aspnet_UserPersonalInfo.Lastname.Contains(partialUsername) || 
                        u.UserName.Contains(partialUsername)) )
                        select new {u.UserId, u.UserName, u.aspnet_UserPersonalInfo.Firstname, u.aspnet_UserPersonalInfo.Lastname };
            return users.ToList();
        }

        public object GetUsersWithRoles(string partialUsername)
        {
            RenewContext();
            var users = from u in Context.aspnet_Users
                        .Include("aspnet_Roles")
                        where ((partialUsername == null || partialUsername == string.Empty) ||
                        (u.aspnet_UserPersonalInfo.Firstname.Contains(partialUsername) || u.aspnet_UserPersonalInfo.Lastname.Contains(partialUsername) ||
                        u.UserName.Contains(partialUsername)))
                        select new
                        {
                            u.UserId,
                            u.UserName,
                            u.aspnet_UserPersonalInfo.Firstname,
                            u.aspnet_UserPersonalInfo.Lastname,
                            Roles = from r in u.aspnet_Roles
                                    select new { r.RoleId, r.RoleName }
                        };
            return users.ToList();
        }

        public void DeleteUser(Guid userId)
        {
            RenewContext();
            var user = Context.aspnet_Users.Include("aspnet_UsersInRoles").FirstOrDefault(u => u.UserId == userId);
            if (user != null)
            {
                Context.DeleteObject(user);
                Context.SaveChanges();
            }
        }

        public void DeleteUserFromRole(Guid userId, Guid roleId)
        {
            RenewContext();
            var user = Context.aspnet_Users.Include("aspnet_Roles").FirstOrDefault(u => u.UserId == userId);
            if (user != null)
            {
                var role = user.aspnet_Roles.FirstOrDefault(ur => ur.RoleId == roleId);
                if (role != null)
                {
                    Context.DeleteObject(role);
                    Context.SaveChanges();
                }
            }
        }

        public void AddUserToRole(Guid userId, Guid roleId)
        {
            RenewContext();
            var user = Context.aspnet_Users.Include("aspnet_UsersInRoles").FirstOrDefault(u => u.UserId == userId);
            if (user != null)
            {
                var role = user.aspnet_Roles.FirstOrDefault(ur => ur.RoleId == roleId);
                //only associate the role with the user if not already associcated
                if (role == null)
                {
                    var newRole = Context.aspnet_Roles.FirstOrDefault(r => r.RoleId == roleId);
                    if (newRole == null)
                    {
                        throw new ArgumentException("Role not found.");
                    }
                    else
                    {
                        user.aspnet_Roles.Add(newRole);
                        Context.SaveChanges();
                    }
                }
            }
            else
            {
                throw new ArgumentException("User not found.");
            }
            return;
        }

        #endregion
    }
}
